home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / iff / if2sun14.1 < prev    next >
Internet Message Format  |  1989-06-22  |  43KB

  1. Path: xanth!ukma!rutgers!apple!oliveb!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i161:  iff2sun - convert iff to sun rasterfile format v1.4
  5. Message-ID: <111706@sun.Eng.Sun.COM>
  6. Date: 22 Jun 89 06:27:24 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 1621
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: raz@kilowatt (Steve -Raz- Berry)
  12. Posting-number: Volume 89, Issue 161
  13. Archive-name: iff/iff2sun14.1
  14.  
  15. Here's the latest iff2sun.  This one does HAM!  Enjoy.
  16.  
  17. [Compile and run this on a Sun workstation, not your Amiga.  ..bob]
  18.  
  19. # This is a shell archive.
  20. # Remove anything above and including the cut line.
  21. # Then run the rest of the file through 'sh'.
  22. # Unpacked files will be owned by you and have default permissions.
  23. #----cut here-----cut here-----cut here-----cut here----#
  24. #!/bin/sh
  25. # shar: SHell ARchive
  26. # Run the following text through 'sh' to create:
  27. #    iff2sun.n
  28. #    Makefile
  29. #    iff2sun.c
  30. #    convert.c
  31. #    hamtosun
  32. # This is archive 1 of a 1-part kit.
  33. # This archive created: Wed May 31 18:38:31 1989
  34. echo "extracting iff2sun.n"
  35. sed 's/^X//' << \SHAR_EOF > iff2sun.n
  36. X.* uncomment the next line for the Amiga nro program
  37. X.* .so an
  38. X.nr h 5      @" header indent
  39. X.nr i 10     @" normal text indent
  40. X.nr s @ni-@nh     @" section heading indent (to the LEFT)
  41. X.TH IFF2SUN 1 "5/29/89" "Version 1.4" "UNIX UTILITIES" "Checkered Ball"
  42. X.* .TH IFF2SUN 1 "Checkered Ball" "UNIX UTILITIES" "Version 1.4"
  43. X.sp 2
  44. X.SH NAME
  45. Xiff2sun/convert - 
  46. X.BR "Amiga
  47. Xto Sun rasterfile conversion program
  48. X.SH SYNOPSIS
  49. X.in +5
  50. X.ta +0
  51. X.ti -5
  52. X.BR "iff2sun [-chp] [infile] [outfile]
  53. X.sp 1
  54. Xif infile is not specified stdin is used.
  55. Xif outfile is not specified then stdout is used.
  56. X.br
  57. X-c yields a color rasterfile (greyscale is the default).
  58. X.br
  59. X-h switches extra half-bright mode on.
  60. X.br
  61. X-p enables horizontal pixel replication. This 
  62. X.br 
  63. X.in +3
  64. Xswitch is usefull for lores and HAM pictures to
  65. Xoffset the aspect ratio difference between the
  66. Xtwo machines (also EHB).
  67. X.in -3
  68. X.sp 1
  69. X.ti -5
  70. X.BR "convert [-c n] [-f] infile outfile
  71. X.sp 1
  72. Xthe (in/out)files MUST be entered (or you get an error message).
  73. X.br
  74. X-c n Set the output colortable to n entries. The default
  75. Xis 256 colors.
  76. X.br
  77. X-f Use Floyd-Steinberg dithering on the output.
  78. X.sp 1
  79. X.in -5
  80. X.ta
  81. X.SH "DESCRIPTION
  82. X.IR "IFF2SUN & CONVERT
  83. X.sp 1
  84. XWhat's it do? This little guy reads an Amiga IFF ILBM file and 
  85. Xoutputs Sun rasterfile format. GIGO (Georgous In Garbage Out).
  86. X.PP
  87. XFor HAM pictures 
  88. X.IR "iff2sun
  89. Xsimply outputs an RGB color file that the Sun
  90. XWILL NOT UNDERSTAND. You then need to run another program called
  91. X.IR "convert
  92. Xto format it into a Sun rasterfile. 
  93. X.PP
  94. XTo properly use this program, you must unshar the distribution
  95. Xand type 'make'. Place the binaries in a convient directory.
  96. XMAKE your executables on a Sun! It does you very little good
  97. Xto try to compile this on your Amiga.
  98. X.PP
  99. X.BR "Convert
  100. Xtakes a partly converted iff file, generated by
  101. X.BR "iff2sun,
  102. Xand converts it the rest of the way to produce a Sun rasterfile.
  103. XThe only supported and tested use of convert is 
  104. X.BR "convert 
  105. X.IR "in out.
  106. XThe other documented switches that the program accepts are not
  107. Xtested at this time.
  108. X.sp 1
  109. X.SH "CONVERTING A HAM PICTURE:
  110. X.PP
  111. XIn order to do conversion from a HAM Iff to a Sun readable
  112. Xfile format, I had to find a routine that would do color quantization
  113. Xfrom 4096 colors to 256. I was able to modify a program released in
  114. X1982 at SIGGRAPH to do this function. Unfortunately, integrating this 
  115. Xinto iff2sun would prove to be too much trouble. Instead I modified
  116. Xiff2sun to detect when it was working on a HAM picture, and do a straight
  117. XRGB color dump, and then use the secondary program to finish doing the
  118. Xcolor quantization.
  119. XSo, when you want to do HAM conversion, follow a sequence like
  120. Xthis:
  121. X.sp 1
  122. X.in +5
  123. X.BR "iff2sun -cp porche930 porche930.out
  124. X.br
  125. X.BR "convert porche930.out porche930.pic
  126. X.in -5
  127. X.sp 1
  128. XThe resulting porche930.pic, in this case, will be a Sun readable
  129. X8 bit plane rasterfile. You can then go and do some dithering or whatever
  130. Xit is that you want to do. There is a supplied script called hamtosun
  131. Xthat will do all of the standard things to convert a ham picture.
  132. X.PP
  133. X.BR "Iff2sun
  134. Xoutputs an 8 bitplane sun rasterfile with a color table,
  135. X(EXCEPT WHEN A HAM PICTURE IS DETECTED, THEN YOU NEED TO RUN 
  136. X.BR "CONVERT
  137. X) which defaults to shades of gray. Using the -c color flag will
  138. Xput the IFF
  139. X.BR "Amiga
  140. Xcolor table into the rasterfile. If you want to display
  141. Xthis on a monochrome tube (which is what I have) you should go 
  142. Xthrough the folowing steps:
  143. X.sp 1
  144. X.in +5
  145. X1> iff2sun inputfile outputfile
  146. X.br
  147. X2> rastrepl outputfile output.bigger
  148. X.br
  149. X3> rasfilter8to1 -d output.bigger output.mono
  150. X.in -5
  151. X.sp 1
  152. XThe rastrepl just pixel replicates the image so that it is large
  153. Xenough to see the detail. you can run this as many times as you
  154. Xlike, but remember the image quadruples each time you use it.
  155. XMost sane people will only run it once.
  156. X.PP
  157. XNOTE: For HAM conversion you NEED to include the -c switch. The
  158. Xcolor tables are used internally to simulate the Amiga HAM mode.
  159. X.PP
  160. XThe rasfilter8to1 program converts the color file (8 bit
  161. Xplanes) to mono (1 plane) and does some fancy dithering (-d).
  162. XTo prepare an image for a color system, just include
  163. Xthe -c switch and either display it as it is, or replicate it
  164. Xto the desired size first.
  165. X.PP
  166. XBoth the rastrepl and rasfilter8to1 program are part of a standard Sun
  167. Xrelease. They should be included on your system.
  168. X.PP
  169. XUsing 
  170. X.IR "Extra-half-bright
  171. Xor 
  172. X.IR "HAM
  173. Xmode, or any 320x400 format will
  174. Xproduce an image that will looked elongated on a Sun screen. There
  175. Xare several ways to fix this. The easiest is to convert your pictures
  176. Xto 640x400 mode and then display them. The second easiest is to rip
  177. Xout 1/3 of the horizontal scan lines in the resultant image. The third
  178. Xis to have ME write iff2sun to pixel replicate horizontally to offset
  179. Xthe aspect ratio change. If the third option is the only one acceptable
  180. Xto you, then you are in luck. All you have to do is run iff2sun with
  181. Xthe -p switch on the command line. You will now get pictures that will look 
  182. Xsomewhat better in this 320 (lo-res) mode. Remember, the executable
  183. Xat this time only pixel-replicates in the horizontal direction. 
  184. XThat means that a pixel replicated
  185. X640 (hi-res) image will come out 1280x400 before you do anything to it. 
  186. XIt is recommended that you pixel replicate your HAM pictures.
  187. X.sp 1  
  188. X.SH "Limitations:
  189. XI have only tested this on DPaintII images, it is
  190. Xvery possible that it might break with other formats.
  191. XUnlikely, but possible :*)
  192. X.sp 1
  193. X.SH "Revision History:
  194. X.sp 1
  195. X10/31/88 First release, does only simple conversion and no color.
  196. X.sp 1  
  197. X12/88 Re-released with color support. Unfortunately few if any
  198. Xone saw this release (it got lost on the way to the moderator)
  199. XThis modification is Mark's claim to fame.
  200. X.sp 1  
  201. X4/26/89 Added Extra-half-bright support, also looking for the
  202. Xbest way to convert HAM (4096) to 8 bit (256) format.
  203. XAlso stuck in the pixel replicating code (trivial).
  204. X.sp 1
  205. X5/26/89 Added HAM mode conversion (with convert) and fixed an iff
  206. Xparsing bug (parse()), and added new argument parsing supplied
  207. Xby Tony Schene. The original convert.c was supplied by
  208. XTony Kennedy as well as the bug report on DPaintIII images.
  209. X.sp 1
  210. X.SH "AUTHORS
  211. X.sp 1
  212. X.PP
  213. XThis Program created (under tremendous pressure) by Steve Berry
  214. Xwith help and modifications by Mark Thompson, Tony Schene and
  215. XTony Kennedy.
  216. X.sp 1 
  217. XI hope you guys keep it clean. (If you don't, let me know :-)
  218. X.sp 1  
  219. X.in +3
  220. XSteve Berry ...sun!kilowatt!raz 
  221. X.br
  222. Xor raz%kilowatt.EBay@@sun.com or even BIX: razberry
  223. X.sp 1
  224. XMark Thompson  ...decvax!savax!thompson
  225. X.in -3
  226. X.sp 1
  227. X-------
  228. X.br
  229. X.IR "This is the revision 2 update information as posted by Mark Thompson.
  230. X.sp 1
  231. XWell I said I would do it, so here it is....the modified and improved
  232. Xversion of iff2sun. The following changes have been made:
  233. X.sp 1
  234. X1) Can now convert IFF images up to 1024 lines vertical resolution.
  235. X    (horizontal res is still 1024)
  236. X.br
  237. X2) Improved greyscale contrast.
  238. X.br
  239. X3) Now generates a Sun Rasterfile colormap.
  240. X.br
  241. X4) Supports either greyscale or color output.
  242. X.sp 1
  243. XAs for the problems some people have been having with the notorious
  244. X'compression messed' error, it seems this is due to certain implementations
  245. Xof kermit. Binary mode kermit in vt100 on the Amiga does work. If you
  246. Xdon't have any luck with this method, uuencode seems to perform flawlessly.
  247. X.sp 1
  248. XMark Thompson
  249. X.br
  250. Xdecvax!savax!thompson
  251. X
  252. X
  253. X
  254. SHAR_EOF
  255. echo "extracting Makefile"
  256. sed 's/^X//' << \SHAR_EOF > Makefile
  257. X#
  258. X#    Makefile for iff2sun
  259. X#
  260. X#    Steve -Raz- Berry
  261. X#    4/25/89
  262. X#
  263. XCFLAGS = -O
  264. X#
  265. X
  266. XOBJS = iff2sun.o convert.o
  267. X
  268. Xall:    iff2sun convert doc
  269. X
  270. Xiff2sun:    $(OBJS)
  271. X    cc $(CFLAGS) -o $@ $@.c
  272. X
  273. Xconvert:    $(OBJS)
  274. X    cc $(CFLAGS) -o $@ $@.c
  275. X
  276. Xclean:
  277. X    rm $(OBJS)
  278. X
  279. Xdoc:    $(OBJS)
  280. X    nroff -man iff2sun.n > iff2sun.doc
  281. X
  282. Xshar:    
  283. X    shar -f iff2sun.$@ iff2sun.n Makefile iff2sun.c convert.c hamtosun
  284. X
  285. SHAR_EOF
  286. echo "extracting iff2sun.c"
  287. sed 's/^X//' << \SHAR_EOF > iff2sun.c
  288. X/*
  289. X**      This Program created (under tremendous pressure) by Steve Berry
  290. X**      with help and modifications by Mark Thompson and others.
  291. X**
  292. X**      I hope you guys keep it clean. (If you don't, let me know :-)
  293. X**
  294. X**      Status: PD all the way.
  295. X**
  296. X**      Please read the file named DOC, that came with this distribution for
  297. X**      information on how to use iff2sun.
  298. X**
  299. X**    Limitations:
  300. X**          I have only tested this on DPaintII images, it is
  301. X**        very possible that it might break with other formats.
  302. X**        Unlikely, but possible :*)
  303. X**
  304. X**    CREDITS:
  305. X**            Mark Thompson
  306. X**            Steve (Raz) Berry
  307. X**
  308. X**    Contacts:
  309. X**                Steve Berry ...sun!kilowatt!raz or 
  310. X**                                             raz%kilowatt.EBay@sun.com
  311. X**                                          BIX: razberry
  312. X**                              Mark Thompson  ...decvax!savax!thompson
  313. X**
  314. X**      Revision History:
  315. X**
  316. X**      10/31/88 First release, does only simple conversion and no color.
  317. X**
  318. X**      12/88    Re-released with color support. Unfortunately few if any
  319. X**               one saw this release (it got lost on the way to the moderator)
  320. X**               (This is Mark's claim to fame)
  321. X**
  322. X**      4/26/89  Added Extra-half-bright support, also looking for the
  323. X**               best way to convert HAM (4096) to 8 bit (256) format.
  324. X**
  325. X**    5/26/89     Added HAM mode conversion (with convert) and fixed an iff
  326. X**         parsing bug (parse()), and added new argument parsing supplied
  327. X**         by Tony Schene. The original convert.c was supplied by
  328. X**         Tony Kennedy as well as the bug report on DPaintIII images.
  329. X*/
  330. X
  331. X#include <sys/types.h>
  332. X#include <stdio.h>
  333. X#include <rasterfile.h>
  334. X
  335. X#define HAM 0x800       /* Amiga Viewmodes */
  336. X#define HALF 0x80
  337. X#define HIRES 0x8000
  338. X#define LACE 0x4
  339. X#define TRUE 1
  340. X#define FALSE 0
  341. X
  342. X/* Stupic C needs to be told about functions used before they
  343. X   are defined */
  344. X
  345. Xunsigned char RGBtoLuma();
  346. Xlong parse();
  347. X
  348. X/* Some variables and arrays */
  349. X
  350. Xu_char    rmap[128],rhmap[128];
  351. Xu_char    gmap[128],ghmap[128];
  352. Xu_char    bmap[128],bhmap[128];
  353. Xu_char currentcolor[3];
  354. Xu_char scanline[1024][6][128]; /* vert, planes, width (bytes) */
  355. X
  356. Xlong width, hieght, planes, hammode, numcolors;
  357. Xlong temp, compress, i, j, k, l;
  358. Xint colorpic=FALSE, halfb = FALSE, pixelrep = FALSE;
  359. Xchar *Usage = "Usage: %s [ -chp ] [ infile ] [ outfile ]\n";
  360. X
  361. Xmain(argc,argv)
  362. Xint argc;
  363. Xchar **argv;
  364. X{
  365. X    struct rasterfile header;
  366. X    unsigned char clr;
  367. X    long formsize, twidth, thieght;
  368. X    static char chunk[5];
  369. X    FILE *inh, *outh;
  370. X    char    *progname= argv[0];
  371. X    char c;
  372. X    extern char *optarg;
  373. X    extern int optind;
  374. X        
  375. X    chunk[4] = 0;
  376. X        
  377. X    inh = stdin;
  378. X    outh = stdout;
  379. X
  380. X    while ((c = getopt (argc, argv, "chp")) != -1)
  381. X        switch (c) {
  382. X        case 'c':
  383. X            colorpic = TRUE;
  384. X            fprintf(stderr,"Color output selected\n");
  385. X            break;
  386. X        case 'h':
  387. X            halfb = TRUE;
  388. X            fprintf(stderr,"Extra Half-bright selected\n");
  389. X            break;
  390. X        case 'p':
  391. X            pixelrep = TRUE;
  392. X            break;
  393. X        default:
  394. X            fprintf (stderr, Usage, argv[0]);
  395. X            exit (1);
  396. X          }
  397. X    if (optind < argc)
  398. X        inh = fopen(argv[optind],"r");
  399. X    if (++optind < argc)
  400. X        outh = fopen(argv[optind],"w");
  401. X    if (++optind < argc) {
  402. X        fprintf (stderr, Usage, argv[0]);
  403. X        exit (1);
  404. X    }
  405. X        
  406. X    if (inh == NULL){
  407. X        perror(argv[1]);
  408. X        exit(-10);
  409. X    }        
  410. X
  411. X    if (outh == NULL){
  412. X        perror(argv[2]);
  413. X        exit(-10);
  414. X    }        
  415. X
  416. X    /* Now comes the fun part... Reading the ILBM's */
  417. X        
  418. X    if (parse(inh,"FORM")) {
  419. X        perror("I don't think that this is an IFF file");
  420. X        exit(-10);
  421. X    }
  422. X
  423. X    fread(&formsize, 4, 1, inh);    /* length of the FORM */
  424. X
  425. X    if (parse(inh,"ILBM")) {
  426. X        perror("I don't think that this is an ILBM");
  427. X        exit(-10);
  428. X    }
  429. X
  430. X    if (parse(inh,"BMHD")) { 
  431. X        perror("Bad format for ILBM.");
  432. X        exit(-10);
  433. X    }
  434. X
  435. X    cc(chunk);
  436. X    fread(chunk, 4, 1, inh);    /* length of the BMHD */
  437. X
  438. X    cc(chunk);
  439. X    fread(chunk, 2, 1, inh);    /* width of bitmap */
  440. X    width = *((short *)chunk);
  441. X
  442. X    cc(chunk);
  443. X    fread(chunk, 2, 1, inh);    /* Height of bitmap */
  444. X    hieght = *((short *)chunk);
  445. X
  446. X    fread(chunk, 4, 1, inh);    /* Don't want the orgins */
  447. X
  448. X    cc(chunk);
  449. X    fread(chunk, 1, 1, inh);    /* # of Planes */
  450. X    planes = *((unsigned char *)chunk);
  451. X
  452. X    fread(chunk, 1, 1, inh);    /* Ignore the Mask */
  453. X
  454. X    cc(chunk);
  455. X    fread(chunk, 1, 1, inh);    /* Compression? */
  456. X
  457. X    compress = *((unsigned char *)chunk);
  458. X
  459. X    fread(chunk, 1, 1, inh);    /* just a pad byte */
  460. X
  461. X/***********************************************************************
  462. X**    DpaintII does not use the CAMG chunk, so we will have to ignore
  463. X**    it for now...
  464. X***********************************************************************/
  465. X
  466. X/*    if (planes == 6) {
  467. X        perror("Sorry, I can't do HAM or Halfbright.");
  468. X        exit(0);
  469. X    } */
  470. X
  471. X    if (parse(inh,"CMAP")) {
  472. X        perror("Bad format for ILBM, couldn't find Color Map.");
  473. X    exit(-10);
  474. X    } 
  475. X
  476. X    cc(chunk);
  477. X    fread(chunk, 4, 1, inh);    /* # of color registers */
  478. X    numcolors = *((long *)chunk);
  479. X        
  480. X    for(i=0; i<64; i++) {
  481. X      rmap[i]= i;
  482. X      gmap[i]= i;
  483. X      bmap[i]= i;
  484. X    }
  485. X
  486. X    numcolors = numcolors/3 ;
  487. X    for (i=0;i<numcolors;i++){
  488. X        fread(chunk, 3, 1, inh);
  489. X        chunk[3] = 0; chunk[4] = 0; 
  490. X        chunk[0] = (chunk[0] >> 4) & 0x0f;
  491. X        chunk[2] = (chunk[2] >> 4) & 0x0f;
  492. X        chunk[1] = (chunk[1] >> 4) & 0x0f;
  493. X        if(colorpic==TRUE) {
  494. X          rmap[i] = (chunk[0] << 4) | chunk[0];
  495. X          gmap[i] = (chunk[1] << 4) | chunk[1];
  496. X          bmap[i] = (chunk[2] << 4) | chunk[2];
  497. X        } else {
  498. X          rmap[i] = RGBtoLuma(chunk);
  499. X          gmap[i] = RGBtoLuma(chunk);
  500. X          bmap[i] = RGBtoLuma(chunk);
  501. X        }
  502. X        if (halfb == TRUE) {
  503. X          rhmap[i] = rmap[i]>>1;
  504. X          ghmap[i] = gmap[i]>>1;
  505. X          bhmap[i] = bmap[i]>>1;
  506. X        }
  507. X    }
  508. X
  509. X    if (numcolors == 2)    /* if a mono image, realign to long word */
  510. X        fread(chunk,1,2,inh);
  511. X
  512. X    if (parse(inh,"BODY")){
  513. X        perror("No BODY data.");
  514. X        exit(0);
  515. X    }
  516. X
  517. X    if ((planes == 6) && (halfb == TRUE) && (numcolors == 16)
  518. X          || (planes != 6) && (halfb == TRUE)){
  519. X      perror("You specified Half-Bright, but file is not in the correct format\n");
  520. X      exit(0);
  521. X    }
  522. X
  523. X    if ((planes == 6) && (halfb != TRUE)) {
  524. X      fprintf(stderr, "Ham mode... raw color output initiated.\n");
  525. X      hammode = TRUE;
  526. X    }
  527. X
  528. X    fread(chunk, 4, 1, inh);    /* length of body */
  529. X
  530. X    if (!hammode) {
  531. X      header.ras_magic= 0x59a66a95;
  532. X      if (pixelrep == FALSE)
  533. X        header.ras_width= width;
  534. X      else
  535. X        header.ras_width= width * 2;
  536. X      header.ras_height= hieght;
  537. X      header.ras_depth= 8;
  538. X      if (pixelrep == FALSE)
  539. X        header.ras_length= width * hieght;
  540. X      else
  541. X        header.ras_length= width * 2 * hieght;
  542. X      header.ras_type= RT_STANDARD;
  543. X      header.ras_maptype= RMT_EQUAL_RGB;
  544. X      header.ras_maplength= 3*256;
  545. X
  546. X/* Write out the rasterfile header to the ouput */
  547. X
  548. X      fwrite(&header, sizeof(header), 1, outh);
  549. X
  550. X/* Write out the red colormap to the ouput */
  551. X
  552. X
  553. X      if (fwrite(rmap, sizeof(rmap), 1, outh) == 0) {
  554. X        perror(progname);
  555. X        exit(1);
  556. X      } 
  557. X      if (halfb == TRUE) 
  558. X        fwrite(rhmap, sizeof(rhmap), 1, outh);
  559. X      else 
  560. X        fwrite(rmap, sizeof(rmap), 1, outh);
  561. X
  562. X/* Write out the green colormap to the ouput */
  563. X    
  564. X      if (fwrite(gmap, sizeof(gmap), 1, outh) == 0) {
  565. X        perror(progname);
  566. X        exit(1);
  567. X      } 
  568. X      if (halfb == TRUE) 
  569. X        fwrite(ghmap, sizeof(ghmap), 1, outh);
  570. X      else 
  571. X        fwrite(gmap, sizeof(gmap), 1, outh);
  572. X
  573. X/* Write out the blue colormap to the ouput */
  574. X
  575. X      if (fwrite(bmap, sizeof(bmap), 1, outh) == 0) {
  576. X        perror(progname);
  577. X        exit(1);
  578. X      } 
  579. X      if (halfb == TRUE) 
  580. X        fwrite(bhmap, sizeof(bhmap), 1, outh);
  581. X      else 
  582. X        fwrite(bmap, sizeof(bmap), 1, outh);
  583. X    }
  584. X    else {
  585. X      twidth = width;
  586. X      if (pixelrep) {
  587. X        twidth = width * 2;
  588. X      }
  589. X      fwrite(&twidth, 4, 1, outh);
  590. X      fwrite(&hieght, 4, 1, outh);
  591. X    }
  592. X
  593. X/* This part does all the work */
  594. X
  595. X/* Either we uncompress the file, or we read it in... */
  596. X
  597. X    if (compress == 1)
  598. X      uncompress(planes, width, inh);
  599. X    else 
  600. X      for(k = 0;k<hieght;k++)
  601. X        for(i = 0;i<planes;i++) {
  602. X          for(j=0;j<width/8;j++){
  603. X        cc(chunk);
  604. X        if(feof(inh))
  605. X          continue;
  606. X        fread(chunk, 1, 1, inh);
  607. X        scanline[k][i][j] = *((unsigned char *)chunk);
  608. X          }
  609. X        }
  610. X
  611. X/* Here we take the data and output it (finally!) */
  612. X
  613. X    currentcolor[0] = rmap[0];
  614. X    currentcolor[1] = gmap[0];
  615. X    currentcolor[2] = bmap[0];
  616. X
  617. X    for(j = 0;j<hieght;j++){
  618. X      for(i = 0;i<width/8;i++)
  619. X        process_pixel(i,j,outh);
  620. X    }
  621. X    fclose(inh);
  622. X    fclose(outh);
  623. X} /* end of main */
  624. X
  625. X/* The uncompression routine                     */
  626. X/* Here we uncompress the data for the number of planes     */
  627. X/* and store it in the global array scanline[][][]         */
  628. X/* Credits: Leo (the great Caped one) was the originator of the */
  629. X/* code I ripped this off from.                 */
  630. X
  631. Xuncompress(planes, width, inh)
  632. XFILE *inh;
  633. Xlong planes, width;
  634. X{
  635. X    long i,j,count,bytesperrow;
  636. X    char len;
  637. X    unsigned char byte;
  638. X
  639. X    for(i=0;i<hieght;i++){
  640. X        for(j=0;j<planes;j++){
  641. X            count = 0;
  642. X            bytesperrow = width / 8;
  643. X            while(bytesperrow > 0){
  644. X                if ((len = getc(inh)) >= 0){
  645. X                    bytesperrow -= ++len;
  646. X                    fread(&scanline[i][j][count],len,1,inh);
  647. X                    count += len;
  648. X                } else if (len == -128)
  649. X                    ;
  650. X                else if (len < 0){
  651. X                    len = -len + 1;
  652. X                    bytesperrow -= len;
  653. X                    byte = getc(inh);
  654. X                    while(--len >= 0)
  655. X                        scanline[i][j][count++] = byte;
  656. X                }
  657. X            }
  658. X            if(bytesperrow)
  659. X                perror("Compression is messed.");
  660. X        }
  661. X        
  662. X    }
  663. X}
  664. X
  665. X
  666. X/* RGBtoLuma converts the colortable from the Amiga to Luminance information */
  667. X/* This routine was written by Mark Thompson                      */
  668. X
  669. Xunsigned char RGBtoLuma(color)
  670. Xunsigned char *color;
  671. X{
  672. X    unsigned char r, g, b;
  673. X    unsigned char grey;
  674. X    float fgrey;
  675. X
  676. X    r = (color[0] << 4) + color[0];
  677. X    g = (color[1] << 4) + color[1];
  678. X    b = (color[2] << 4) + color[2];
  679. X    fgrey = 0.3 * r + 0.59 * g + 0.11 * b + 0.5;
  680. X    grey = fgrey;
  681. X    return grey;
  682. X}
  683. X
  684. X/* Process the byte for the scanline         */
  685. X/* Can you say shift 3 times fast?         */
  686. X
  687. Xprocess_pixel(byte,scan,outh)
  688. XFILE *outh;
  689. Xunsigned char byte;
  690. Xlong scan;
  691. X{
  692. X    long j, i, p, result = 0;
  693. X    unsigned char temp;
  694. X
  695. X    temp = 0; result = 0;
  696. X    for(i=7;i>=0;i--){
  697. X        for(p=0;p<planes;p++) 
  698. X            result = ((((1 << i) & scanline[scan][p][byte])>>i)<<p) | result;
  699. X        result = result & 0x3f;
  700. X        temp = result;
  701. X
  702. X        if (hammode) {
  703. X          temp = (result & 0x30) >> 4;
  704. X          switch (temp){
  705. X          case 0x0:
  706. X            temp = result & 0x0f;
  707. X            currentcolor[2] = bmap[temp]<<4;
  708. X            currentcolor[1] = gmap[temp]<<4; 
  709. X            currentcolor[0] = rmap[temp]<<4;
  710. X            break;
  711. X          case 0x1:
  712. X            result = result & 0x0f;
  713. X            currentcolor[2] = result<<4;
  714. X            break;
  715. X          case 0x2:
  716. X            result = result & 0x0f;
  717. X            currentcolor[0] = result<<4;
  718. X            break;
  719. X          case 0x3:
  720. X            result = result & 0x0f;
  721. X            currentcolor[1] = result<<4;
  722. X            break;
  723. X          }
  724. X
  725. X          fwrite(currentcolor, 1, 3, outh);
  726. X          if (pixelrep == TRUE)
  727. X            fwrite(currentcolor, 1, 3, outh);
  728. X        }
  729. X        else {
  730. X          fwrite(&temp, 1, 1, outh);
  731. X          if (pixelrep == TRUE)
  732. X            fwrite(&temp, 1, 1, outh);
  733. X        }
  734. X        result = 0;
  735. X    }
  736. X}
  737. X
  738. X/* look for a chunk in the file */
  739. Xlong parse(inh, str)
  740. XFILE *inh;
  741. Xchar *str;
  742. X{
  743. X        static char chunk[5];
  744. X        chunk[4] = 0;
  745. X        while (1){
  746. X      fread(chunk, 2, 1, inh);
  747. X      if (strncmp(chunk,str,2) == 0){
  748. X        fread(chunk, 2, 1, inh);
  749. X        if (strncmp(chunk,&str[2],2) == 0)
  750. X          return FALSE;
  751. X      }
  752. X      if(feof(inh) != 0)
  753. X        return TRUE;
  754. X        }
  755. X}
  756. X
  757. X/* Clear Chunk variable */
  758. X
  759. Xcc(chunk)
  760. Xchar chunk[5];
  761. X{
  762. X    register int i;
  763. X    for(i=0;i<5;i++)
  764. X        chunk[i] = 0;
  765. X}
  766. SHAR_EOF
  767. echo "extracting convert.c"
  768. sed 's/^X//' << \SHAR_EOF > convert.c
  769. X
  770. X/*
  771. X * Apply median cut on an image.
  772. X *
  773. X * median [-c n] [-f] input output
  774. X *     -c n        - set colortable size.  Default is 256.
  775. X *     -f        - use Floyd-Steinberg dithering.
  776. X *     -lzw        - compress output with LZW
  777. X *     -none        - use no compression on output
  778. X *     -picio        - use picio compression on output
  779. X *     -packbits    - use packbits compression on output
  780. X *     -rowsperstrip n    - create output with n rows/strip of data
  781. X * (by default the compression scheme and rows/strip are taken
  782. X *  from the input file)
  783. X *
  784. X * Notes:
  785. X *
  786. X * [1] Floyd-Steinberg dither:
  787. X *  I should point out that the actual fractions we used were, assuming
  788. X *  you are at X, moving left to right:
  789. X *
  790. X *            X     7/16
  791. X *         3/16   5/16  1/16    
  792. X *
  793. X *  Note that the error goes to four neighbors, not three.  I think this
  794. X *  will probably do better (at least for black and white) than the
  795. X *  3/8-3/8-1/4 distribution, at the cost of greater processing.  I have
  796. X *  seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
  797. X *  but I have no idea who the credit really belongs to.
  798. X
  799. X *  Also, I should add that if you do zig-zag scanning (see my immediately
  800. X *  previous message), it is sufficient (but not quite as good) to send
  801. X *  half the error one pixel ahead (e.g. to the right on lines you scan
  802. X *  left to right), and half one pixel straight down.  Again, this is for
  803. X *  black and white;  I've not tried it with color.
  804. X *  -- 
  805. X *                        Lou Steinberg
  806. X *
  807. X * [2] Color Image Quantization for Frame Buffer Display, Paul Heckbert,
  808. X *    Siggraph '82 proceedings, pp. 297-307
  809. X */
  810. X#include <stdio.h>
  811. X#include <sys/types.h>
  812. X#include <rasterfile.h>
  813. X
  814. X#define    MAX_CMAP_SIZE    256
  815. X#define    howmany(x, y)    (((x)+((y)-1))/(y))
  816. X#define    streq(a,b)    (strcmp(a,b) == 0)
  817. X
  818. X#define    COLOR_DEPTH    8
  819. X#define    MAX_COLOR    256
  820. X
  821. X#define    B_DEPTH        4        /* # bits/pixel to use */
  822. X#define    B_LEN        (1<<B_DEPTH)
  823. X
  824. X#define    C_DEPTH        2
  825. X#define    C_LEN        (1<<C_DEPTH)    /* # cells/color to use */
  826. X
  827. X#define    COLOR_SHIFT    (COLOR_DEPTH-B_DEPTH)
  828. X#define COMPRESSION_NONE 0
  829. X#define COMPRESSION_PACKBITS 1
  830. X#define COMPRESSION_LZW 2
  831. X#define COMPRESSION_PICIO 3
  832. X
  833. X
  834. Xtypedef    struct colorbox {
  835. X    struct    colorbox *next, *prev;
  836. X    int    rmin, rmax;
  837. X    int    gmin, gmax;
  838. X    int    bmin, bmax;
  839. X    int    total;
  840. X} Colorbox;
  841. X
  842. Xtypedef struct {
  843. X    int    num_ents;
  844. X    int    entries[MAX_CMAP_SIZE][2];
  845. X} C_cell;
  846. X
  847. Xu_short    rm[MAX_CMAP_SIZE], gm[MAX_CMAP_SIZE], bm[MAX_CMAP_SIZE];
  848. Xint    bytes_per_pixel;
  849. Xlong    num_colors, width, hieght, length;
  850. Xint    histogram[B_LEN][B_LEN][B_LEN];
  851. XColorbox *freeboxes;
  852. XColorbox *usedboxes;
  853. XColorbox *largest_box();
  854. XC_cell    **ColorCells;
  855. XFILE    *in, *out;
  856. X
  857. Xchar    *usage = "usage: median [-c n] [-f] [-none] [-lzw] [-picio] [-packbits] [-rowsperstrip r] input output\n";
  858. X
  859. Xmain(argc, argv)
  860. X    int argc;
  861. X    char **argv;
  862. X{
  863. X    struct rasterfile header;
  864. X    int i, j, dither = 0;
  865. X    long chunk;
  866. X    char *ifile_name = NULL, *ofile_name = NULL, color;
  867. X    Colorbox *box_list, *ptr;
  868. X    u_short rowsperstrip = 128, compression = -1, shortv;
  869. X    u_short bitspersample, samplesperpixel, photometric;
  870. X    float floatv;
  871. X
  872. X    num_colors = MAX_CMAP_SIZE;
  873. X    for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
  874. X        if (streq(argv[0], "-f")) {
  875. X            dither = 1;
  876. X            continue;
  877. X        }
  878. X        if (streq(argv[0], "-c")) {
  879. X            argc--, argv++;
  880. X            if (argc < 1) {
  881. X                fprintf(stderr, "-c: missing colormap size\n%s",
  882. X                    usage);
  883. X                exit(1);
  884. X            }
  885. X            num_colors = atoi(argv[0]);
  886. X            if (num_colors > MAX_CMAP_SIZE) {
  887. X                fprintf(stderr,
  888. X                   "-c: colormap too big, max %d\n%s",
  889. X                   MAX_CMAP_SIZE, usage);
  890. X                exit(1);
  891. X            }
  892. X            continue;
  893. X        }
  894. X        if (streq(argv[0], "-none")) {
  895. X            compression = COMPRESSION_NONE;
  896. X            continue;
  897. X        }
  898. X        if (streq(argv[0], "-packbits")) {
  899. X            compression = COMPRESSION_PACKBITS;
  900. X            continue;
  901. X        }
  902. X        if (streq(argv[0], "-lzw")) {
  903. X            compression = COMPRESSION_LZW;
  904. X            continue;
  905. X        }
  906. X        if (streq(argv[0], "-picio")) {
  907. X            compression = COMPRESSION_PICIO;
  908. X            continue;
  909. X        }
  910. X        if (streq(argv[0], "-rowsperstrip")) {
  911. X            argc--, argv++;
  912. X            rowsperstrip = atoi(argv[0]);
  913. X            continue;
  914. X        }
  915. X        fprintf(stderr, "%s: unknown option\n%s", argv[0], usage);
  916. X        exit(1);
  917. X    }
  918. X    if (argc < 2) {
  919. X        fprintf(stderr, "%s", usage);
  920. X        exit(-1);
  921. X    }
  922. X    in = fopen(argv[0], "r");
  923. X    if (in == NULL)
  924. X        exit(-1);
  925. X
  926. X    fread(&width, 4, 1, in); /* Get size of picture */
  927. X    fread(&hieght, 4, 1, in);
  928. X    length = hieght;
  929. X
  930. X    /*
  931. X     * STEP 1:  create empty boxes
  932. X     */
  933. X    usedboxes = NULL;
  934. X    box_list = freeboxes = (Colorbox *)malloc(num_colors*sizeof (Colorbox));
  935. X    freeboxes[0].next = &freeboxes[1];
  936. X    freeboxes[0].prev = NULL;
  937. X    for (i = 1; i < num_colors-1; ++i) {
  938. X        freeboxes[i].next = &freeboxes[i+1];
  939. X        freeboxes[i].prev = &freeboxes[i-1];
  940. X    }
  941. X    freeboxes[num_colors-1].next = NULL;
  942. X    freeboxes[num_colors-1].prev = &freeboxes[num_colors-2];
  943. X
  944. X    /*
  945. X     * STEP 2: get histogram, initialize first box
  946. X     */
  947. X    ptr = freeboxes;
  948. X    freeboxes = ptr->next;
  949. X    if (freeboxes)
  950. X        freeboxes->prev = NULL;
  951. X    ptr->next = usedboxes;
  952. X    usedboxes = ptr;
  953. X    if (ptr->next)
  954. X        ptr->next->prev = ptr;
  955. X    get_histogram(in, ptr);
  956. X
  957. X    /*
  958. X     * STEP 3: continually subdivide boxes until no more free
  959. X     * boxes remain or until all colors assigned.
  960. X     */
  961. X    while (freeboxes != NULL) {
  962. X        ptr = largest_box();
  963. X        if (ptr != NULL)
  964. X            splitbox(ptr);
  965. X        else
  966. X            freeboxes = NULL;
  967. X    }
  968. X
  969. X    /*
  970. X     * STEP 4: assign colors to all boxes
  971. X     */
  972. X    for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next) {
  973. X        rm[i] = ((ptr->rmin + ptr->rmax) << COLOR_SHIFT) / 2;
  974. X        gm[i] = ((ptr->gmin + ptr->gmax) << COLOR_SHIFT) / 2;
  975. X        bm[i] = ((ptr->bmin + ptr->bmax) << COLOR_SHIFT) / 2;
  976. X    }
  977. X
  978. X    fprintf(stderr,"Number of colors used %d\n", i);
  979. X
  980. X    /* We're done with the boxes now */
  981. X    free(box_list);
  982. X    box_list = freeboxes = usedboxes = NULL;
  983. X
  984. X    /*
  985. X     * STEP 5: scan histogram and map all values to closest color
  986. X     */
  987. X    /* 5a: create cell list as described in Heckbert[2] */
  988. X    ColorCells = (C_cell **)calloc(C_LEN*C_LEN*C_LEN, sizeof (C_cell *));
  989. X    /* 5b: create mapping from truncated pixel space to color
  990. X       table entries */
  991. X    map_colortable();
  992. X
  993. X    /*
  994. X     * STEP 6: scan image, match input values to table entries
  995. X     */
  996. X    out = fopen(argv[1], "w");
  997. X    if (out == NULL)
  998. X        exit(-2);
  999. X
  1000. X    header.ras_magic= 0x59a66a95;
  1001. X    header.ras_width= width;
  1002. X      header.ras_height= hieght;
  1003. X      header.ras_depth= 8;
  1004. X    header.ras_length= width * hieght;
  1005. X      header.ras_type= RT_STANDARD;
  1006. X      header.ras_maptype= RMT_EQUAL_RGB;
  1007. X      header.ras_maplength= 3*256;
  1008. X
  1009. X/* Write out the rasterfile header to the ouput */
  1010. X
  1011. X    fwrite(&header, sizeof(header), 1, out);
  1012. X
  1013. X/* Write the colormap to the ouput */
  1014. X
  1015. X    for(i=0;i<256;i++) {
  1016. X      color = (char)rm[i];
  1017. X      fwrite(&color, 1, 1, out);
  1018. X    }
  1019. X
  1020. X    for(i=0;i<256;i++) {
  1021. X      color = (char)gm[i];
  1022. X      fwrite(&color, 1, 1, out);
  1023. X    }
  1024. X
  1025. X    for(i=0;i<256;i++) {
  1026. X      color = (char)bm[i];
  1027. X      fwrite(&color, 1, 1, out);
  1028. X    }
  1029. X
  1030. X    rewind(in);        /* rewind input file XXX */
  1031. X
  1032. X    fread(&chunk, 4, 1, in);
  1033. X    fread(&chunk, 4, 1, in);
  1034. X    if (dither)
  1035. X        quant_fsdither(in, out);
  1036. X    else
  1037. X        quant(in, out);
  1038. X    (void) fclose(out);
  1039. X
  1040. X}
  1041. X
  1042. Xstatic
  1043. Xget_histogram(in, box)
  1044. X    FILE *in;
  1045. X    register Colorbox *box;
  1046. X{
  1047. X    register u_char *inptr;
  1048. X    register int red, green, blue, j, i;
  1049. X    u_char *inline;
  1050. X
  1051. X    i = 24 * width;
  1052. X    inline = (u_char *)malloc(howmany(i, 8));
  1053. X    if (inline == NULL) {
  1054. X        fprintf(stderr, "No space for scanline buffer\n");
  1055. X        exit(-1);
  1056. X    }
  1057. X    box->rmin = box->gmin = box->bmin = 999;
  1058. X    box->rmax = box->gmax = box->bmax = -1;
  1059. X    box->total = width * length;
  1060. X
  1061. X    { register int *ptr = &histogram[0][0][0];
  1062. X      for (i = B_LEN*B_LEN*B_LEN; --i >= 0;)
  1063. X        *ptr++ = 0;
  1064. X    }
  1065. X    for (i = length; i-- > 0;) {
  1066. X        if (fread(inline, width*3, 1, in) <= 0)
  1067. X            break;
  1068. X        inptr = inline;
  1069. X        for (j = width; j-- > 0;) {
  1070. X            red = *inptr++ >> COLOR_SHIFT;
  1071. X            green = *inptr++ >> COLOR_SHIFT;
  1072. X            blue = *inptr++ >> COLOR_SHIFT; 
  1073. X            if (red < box->rmin)
  1074. X                box->rmin = red;
  1075. X                if (red > box->rmax)
  1076. X                box->rmax = red;
  1077. X                if (green < box->gmin)
  1078. X                box->gmin = green;
  1079. X                if (green > box->gmax)
  1080. X                box->gmax = green;
  1081. X                if (blue < box->bmin)
  1082. X                box->bmin = blue;
  1083. X                if (blue > box->bmax)
  1084. X                box->bmax = blue;
  1085. X                histogram[red][green][blue]++;
  1086. X        }
  1087. X    }
  1088. X    free(inline);
  1089. X}
  1090. X
  1091. Xstatic Colorbox *
  1092. Xlargest_box()
  1093. X{
  1094. X    register Colorbox *p, *b;
  1095. X    register int size;
  1096. X
  1097. X    b = NULL;
  1098. X    size = -1;
  1099. X    for (p = usedboxes; p != NULL; p = p->next)
  1100. X        if ((p->rmax > p->rmin || p->gmax > p->gmin ||
  1101. X            p->bmax > p->bmin) &&  p->total > size)
  1102. X                size = (b = p)->total;
  1103. X    return (b);
  1104. X}
  1105. X
  1106. Xstatic
  1107. Xsplitbox(ptr)
  1108. X    register Colorbox *ptr;
  1109. X{
  1110. X    int        hist2[B_LEN];
  1111. X    int        first, last;
  1112. X    register Colorbox    *new;
  1113. X    register int    *iptr, *histp;
  1114. X    register int    i, j;
  1115. X    register int    ir,ig,ib;
  1116. X    register int sum, sum1, sum2;
  1117. X    int        total;
  1118. X    enum { RED, GREEN, BLUE } axis;
  1119. X
  1120. X    /*
  1121. X     * See which axis is the largest, do a histogram along that
  1122. X     * axis.  Split at median point.  Contract both new boxes to
  1123. X     * fit points and return
  1124. X     */
  1125. X    i = ptr->rmax - ptr->rmin;
  1126. X    if (i >= ptr->gmax - ptr->gmin  && i >= ptr->bmax - ptr->bmin)
  1127. X        axis = RED;
  1128. X    else if (ptr->gmax - ptr->gmin >= ptr->bmax - ptr->bmin)
  1129. X        axis = GREEN;
  1130. X    else
  1131. X        axis = BLUE;
  1132. X    /* get histogram along longest axis */
  1133. X    switch (axis) {
  1134. X    case RED:
  1135. X        histp = &hist2[ptr->rmin];
  1136. X            for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
  1137. X            *histp = 0;
  1138. X            for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
  1139. X                iptr = &histogram[ir][ig][ptr->bmin];
  1140. X                for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
  1141. X                    *histp += *iptr++;
  1142. X            }
  1143. X            histp++;
  1144. X            }
  1145. X            first = ptr->rmin;
  1146. X        last = ptr->rmax;
  1147. X            break;
  1148. X    case GREEN:
  1149. X            histp = &hist2[ptr->gmin];
  1150. X            for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
  1151. X            *histp = 0;
  1152. X            for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
  1153. X                iptr = &histogram[ir][ig][ptr->bmin];
  1154. X                for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
  1155. X                    *histp += *iptr++;
  1156. X            }
  1157. X            histp++;
  1158. X            }
  1159. X            first = ptr->gmin;
  1160. X        last = ptr->gmax;
  1161. X            break;
  1162. X    case BLUE:
  1163. X            histp = &hist2[ptr->bmin];
  1164. X            for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) {
  1165. X            *histp = 0;
  1166. X            for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
  1167. X                iptr = &histogram[ir][ptr->gmin][ib];
  1168. X                for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
  1169. X                    *histp += *iptr;
  1170. X                    iptr += B_LEN;
  1171. X                }
  1172. X            }
  1173. X            histp++;
  1174. X            }
  1175. X            first = ptr->bmin;
  1176. X        last = ptr->bmax;
  1177. X            break;
  1178. X    }
  1179. X    /* find median point */
  1180. X    histp = &hist2[first];
  1181. X    sum2 = ptr->total / 2;
  1182. X    histp = &hist2[first];
  1183. X    sum = 0;
  1184. X    for (i = first; i <= last && (sum += *histp++) < sum2; ++i)
  1185. X        ;
  1186. X    if (i == first)
  1187. X        i++;
  1188. X
  1189. X    /* Create new box, re-allocate points */
  1190. X    new = freeboxes;
  1191. X    freeboxes = new->next;
  1192. X    if (freeboxes)
  1193. X        freeboxes->prev = NULL;
  1194. X    if (usedboxes)
  1195. X        usedboxes->prev = new;
  1196. X    new->next = usedboxes;
  1197. X    usedboxes = new;
  1198. X
  1199. X    total = ptr->total;
  1200. X    histp = &hist2[first];
  1201. X    for (sum1 = 0, j = first; j < i; j++)
  1202. X        sum1 += *histp++;
  1203. X    for (sum2 = 0, j = i; j <= last; j++)
  1204. X        sum2 += *histp++;
  1205. X    new->total = sum1;
  1206. X    ptr->total = sum2;
  1207. X
  1208. X    new->rmin = ptr->rmin;
  1209. X    new->rmax = ptr->rmax;
  1210. X    new->gmin = ptr->gmin;
  1211. X    new->gmax = ptr->gmax;
  1212. X    new->bmin = ptr->bmin;
  1213. X    new->bmax = ptr->bmax;
  1214. X    switch (axis) {
  1215. X    case RED:
  1216. X        new->rmax = i-1;
  1217. X            ptr->rmin = i;
  1218. X            break;
  1219. X    case GREEN:
  1220. X            new->gmax = i-1;
  1221. X            ptr->gmin = i;
  1222. X            break;
  1223. X    case BLUE:
  1224. X            new->bmax = i-1;
  1225. X            ptr->bmin = i;
  1226. X            break;
  1227. X    }
  1228. X    shrinkbox(new);
  1229. X    shrinkbox(ptr);
  1230. X}
  1231. X
  1232. Xstatic
  1233. Xshrinkbox(box)
  1234. X    register Colorbox *box;
  1235. X{
  1236. X    register int *histp, ir, ig, ib;
  1237. X
  1238. X    if (box->rmax > box->rmin) {
  1239. X        for (ir = box->rmin; ir <= box->rmax; ++ir)
  1240. X            for (ig = box->gmin; ig <= box->gmax; ++ig) {
  1241. X                histp = &histogram[ir][ig][box->bmin];
  1242. X                    for (ib = box->bmin; ib <= box->bmax; ++ib)
  1243. X                    if (*histp++ != 0) {
  1244. X                        box->rmin = ir;
  1245. X                        goto have_rmin;
  1246. X                    }
  1247. X            }
  1248. X    have_rmin:
  1249. X        if (box->rmax > box->rmin)
  1250. X            for (ir = box->rmax; ir >= box->rmin; --ir)
  1251. X                for (ig = box->gmin; ig <= box->gmax; ++ig) {
  1252. X                    histp = &histogram[ir][ig][box->bmin];
  1253. X                    ib = box->bmin;
  1254. X                    for (; ib <= box->bmax; ++ib)
  1255. X                        if (*histp++ != 0) {
  1256. X                            box->rmax = ir;
  1257. X                            goto have_rmax;
  1258. X                        }
  1259. X                    }
  1260. X    }
  1261. Xhave_rmax:
  1262. X    if (box->gmax > box->gmin) {
  1263. X        for (ig = box->gmin; ig <= box->gmax; ++ig)
  1264. X            for (ir = box->rmin; ir <= box->rmax; ++ir) {
  1265. X                histp = &histogram[ir][ig][box->bmin];
  1266. X                    for (ib = box->bmin; ib <= box->bmax; ++ib)
  1267. X                if (*histp++ != 0) {
  1268. X                    box->gmin = ig;
  1269. X                    goto have_gmin;
  1270. X                }
  1271. X            }
  1272. X    have_gmin:
  1273. X        if (box->gmax > box->gmin)
  1274. X            for (ig = box->gmax; ig >= box->gmin; --ig)
  1275. X                for (ir = box->rmin; ir <= box->rmax; ++ir) {
  1276. X                    histp = &histogram[ir][ig][box->bmin];
  1277. X                    ib = box->bmin;
  1278. X                    for (; ib <= box->bmax; ++ib)
  1279. X                        if (*histp++ != 0) {
  1280. X                            box->gmax = ig;
  1281. X                            goto have_gmax;
  1282. X                        }
  1283. X                    }
  1284. X    }
  1285. Xhave_gmax:
  1286. X    if (box->bmax > box->bmin) {
  1287. X        for (ib = box->bmin; ib <= box->bmax; ++ib)
  1288. X            for (ir = box->rmin; ir <= box->rmax; ++ir) {
  1289. X                histp = &histogram[ir][box->gmin][ib];
  1290. X                    for (ig = box->gmin; ig <= box->gmax; ++ig) {
  1291. X                    if (*histp != 0) {
  1292. X                        box->bmin = ib;
  1293. X                        goto have_bmin;
  1294. X                    }
  1295. X                    histp += B_LEN;
  1296. X                    }
  1297. X                }
  1298. X    have_bmin:
  1299. X        if (box->bmax > box->bmin)
  1300. X            for (ib = box->bmax; ib >= box->bmin; --ib)
  1301. X                for (ir = box->rmin; ir <= box->rmax; ++ir) {
  1302. X                    histp = &histogram[ir][box->gmin][ib];
  1303. X                    ig = box->gmin;
  1304. X                    for (; ig <= box->gmax; ++ig) {
  1305. X                        if (*histp != 0) {
  1306. X                            box->bmax = ib;
  1307. X                            goto have_bmax;
  1308. X                        }
  1309. X                        histp += B_LEN;
  1310. X                    }
  1311. X                    }
  1312. X    }
  1313. Xhave_bmax:
  1314. X    ;
  1315. X}
  1316. X
  1317. Xstatic C_cell *
  1318. Xcreate_colorcell(red, green, blue)
  1319. X    int red, green, blue;
  1320. X{
  1321. X    register int ir, ig, ib, i;
  1322. X    register C_cell *ptr;
  1323. X    int mindist, next_n;
  1324. X    register int tmp, dist, n;
  1325. X
  1326. X    ir = red >> (COLOR_DEPTH-C_DEPTH);
  1327. X    ig = green >> (COLOR_DEPTH-C_DEPTH);
  1328. X    ib = blue >> (COLOR_DEPTH-C_DEPTH);
  1329. X    ptr = (C_cell *)malloc(sizeof (C_cell));
  1330. X    *(ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib) = ptr;
  1331. X    ptr->num_ents = 0;
  1332. X
  1333. X    /*
  1334. X     * Step 1: find all colors inside this cell, while we're at
  1335. X     *       it, find distance of centermost point to furthest corner
  1336. X     */
  1337. X    mindist = 99999999;
  1338. X    for (i = 0; i < num_colors; ++i) {
  1339. X        if (rm[i]>>(COLOR_DEPTH-C_DEPTH) != ir  ||
  1340. X            gm[i]>>(COLOR_DEPTH-C_DEPTH) != ig  ||
  1341. X            bm[i]>>(COLOR_DEPTH-C_DEPTH) != ib)
  1342. X            continue;
  1343. X        ptr->entries[ptr->num_ents][0] = i;
  1344. X        ptr->entries[ptr->num_ents][1] = 0;
  1345. X        ++ptr->num_ents;
  1346. X            tmp = rm[i] - red;
  1347. X            if (tmp < (MAX_COLOR/C_LEN/2))
  1348. X            tmp = MAX_COLOR/C_LEN-1 - tmp;
  1349. X            dist = tmp*tmp;
  1350. X            tmp = gm[i] - green;
  1351. X            if (tmp < (MAX_COLOR/C_LEN/2))
  1352. X            tmp = MAX_COLOR/C_LEN-1 - tmp;
  1353. X            dist += tmp*tmp;
  1354. X            tmp = bm[i] - blue;
  1355. X            if (tmp < (MAX_COLOR/C_LEN/2))
  1356. X            tmp = MAX_COLOR/C_LEN-1 - tmp;
  1357. X            dist += tmp*tmp;
  1358. X            if (dist < mindist)
  1359. X            mindist = dist;
  1360. X    }
  1361. X
  1362. X    /*
  1363. X     * Step 3: find all points within that distance to cell.
  1364. X     */
  1365. X    for (i = 0; i < num_colors; ++i) {
  1366. X        if (rm[i] >> (COLOR_DEPTH-C_DEPTH) == ir  &&
  1367. X            gm[i] >> (COLOR_DEPTH-C_DEPTH) == ig  &&
  1368. X            bm[i] >> (COLOR_DEPTH-C_DEPTH) == ib)
  1369. X            continue;
  1370. X        dist = 0;
  1371. X            if ((tmp = red - rm[i]) > 0 ||
  1372. X            (tmp = rm[i] - (red + MAX_COLOR/C_LEN-1)) > 0 )
  1373. X            dist += tmp*tmp;
  1374. X            if ((tmp = green - gm[i]) > 0 ||
  1375. X            (tmp = gm[i] - (green + MAX_COLOR/C_LEN-1)) > 0 )
  1376. X            dist += tmp*tmp;
  1377. X            if ((tmp = blue - bm[i]) > 0 ||
  1378. X            (tmp = bm[i] - (blue + MAX_COLOR/C_LEN-1)) > 0 )
  1379. X            dist += tmp*tmp;
  1380. X            if (dist < mindist) {
  1381. X            ptr->entries[ptr->num_ents][0] = i;
  1382. X            ptr->entries[ptr->num_ents][1] = dist;
  1383. X            ++ptr->num_ents;
  1384. X            }
  1385. X    }
  1386. X
  1387. X    /*
  1388. X     * Sort color cells by distance, use cheap exchange sort
  1389. X     */
  1390. X    for (n = ptr->num_ents - 1; n > 0; n = next_n) {
  1391. X        next_n = 0;
  1392. X        for (i = 0; i < n; ++i)
  1393. X            if (ptr->entries[i][1] > ptr->entries[i+1][1]) {
  1394. X                tmp = ptr->entries[i][0];
  1395. X                ptr->entries[i][0] = ptr->entries[i+1][0];
  1396. X                ptr->entries[i+1][0] = tmp;
  1397. X                tmp = ptr->entries[i][1];
  1398. X                ptr->entries[i][1] = ptr->entries[i+1][1];
  1399. X                ptr->entries[i+1][1] = tmp;
  1400. X                next_n = i;
  1401. X                }
  1402. X    }
  1403. X    return (ptr);
  1404. X}
  1405. X
  1406. Xstatic
  1407. Xmap_colortable()
  1408. X{
  1409. X    register int *histp = &histogram[0][0][0];
  1410. X    register C_cell *cell;
  1411. X    register int j, tmp, d2, dist;
  1412. X    int ir, ig, ib, i;
  1413. X
  1414. X    for (ir = 0; ir < B_LEN; ++ir)
  1415. X        for (ig = 0; ig < B_LEN; ++ig)
  1416. X            for (ib = 0; ib < B_LEN; ++ib, histp++) {
  1417. X                if (*histp == 0) {
  1418. X                    *histp = -1;
  1419. X                    continue;
  1420. X                }
  1421. X                cell = *(ColorCells +
  1422. X                    (((ir>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
  1423. X                    ((ig>>(B_DEPTH-C_DEPTH)) << C_DEPTH) +
  1424. X                    (ib>>(B_DEPTH-C_DEPTH))));
  1425. X                if (cell == NULL )
  1426. X                    cell = create_colorcell(
  1427. X                        ir << COLOR_SHIFT,
  1428. X                        ig << COLOR_SHIFT,
  1429. X                        ib << COLOR_SHIFT);
  1430. X                dist = 9999999;
  1431. X                for (i = 0; i < cell->num_ents &&
  1432. X                    dist > cell->entries[i][1]; ++i) {
  1433. X                    j = cell->entries[i][0];
  1434. X                    d2 = rm[j] - (ir << COLOR_SHIFT);
  1435. X                    d2 *= d2;
  1436. X                    tmp = gm[j] - (ig << COLOR_SHIFT);
  1437. X                    d2 += tmp*tmp;
  1438. X                    tmp = bm[j] - (ib << COLOR_SHIFT);
  1439. X                    d2 += tmp*tmp;
  1440. X                    if (d2 < dist) {
  1441. X                        dist = d2;
  1442. X                        *histp = j;
  1443. X                    }
  1444. X                }
  1445. X            }
  1446. X}
  1447. X
  1448. X/*
  1449. X * straight quantization.  Each pixel is mapped to the colors
  1450. X * closest to it.  Color values are rounded to the nearest color
  1451. X * table entry.
  1452. X */
  1453. Xstatic
  1454. Xquant(in, out)
  1455. X    FILE *in, *out;
  1456. X{
  1457. X    u_char    *outline, *inline;
  1458. X    register u_char    *outptr, *inptr;
  1459. X    register int i, j, red, green, blue;
  1460. X
  1461. X    i = 24 * width;
  1462. X    inline = (u_char *)malloc(howmany(i, 8));
  1463. X    outline = (u_char *)malloc(width);
  1464. X    for (i = 0; i < length; i++) {
  1465. X        if (fread(inline, 3*width, 1, in) <= 0)
  1466. X            break;
  1467. X        inptr = inline;
  1468. X        outptr = outline;
  1469. X        for (j = 0; j < width; j++) {
  1470. X            red = *inptr++ >> COLOR_SHIFT;
  1471. X            green = *inptr++ >> COLOR_SHIFT;
  1472. X            blue = *inptr++ >> COLOR_SHIFT;
  1473. X            *outptr++ = histogram[red][green][blue];
  1474. X        }
  1475. X        if (fwrite(outline, width, 1, out) <= 0)
  1476. X            break;
  1477. X    }
  1478. X    free(inline);
  1479. X    free(outline);
  1480. X}
  1481. X
  1482. Xstatic
  1483. Xquant_fsdither(in, out)
  1484. X    FILE *in, *out;
  1485. X{
  1486. X    u_char *outline, *inline, *inptr;
  1487. X    short *thisline, *nextline, *tmpptr;
  1488. X    register u_char    *outptr;
  1489. X    register short *thisptr, *nextptr;
  1490. X    register int i, j, tmp;
  1491. X    int imax, jmax, lastline, lastpixel;
  1492. X
  1493. X    imax = length - 1;
  1494. X    jmax = width - 1;
  1495. X    i = 12 * width;
  1496. X    inline = (u_char *)malloc(howmany(i, 8));
  1497. X    thisline = (short *)malloc(width * 3 * sizeof (short));
  1498. X    nextline = (short *)malloc(width * 3 * sizeof (short));
  1499. X    outline = (unsigned char *) malloc(width);
  1500. X
  1501. X    /*
  1502. X     * Get first line
  1503. X     */
  1504. X    if (fread(inline, 3*width, 1, in) <= 0)
  1505. X        return;
  1506. X    inptr = inline;
  1507. X    nextptr = nextline;
  1508. X    for (j = 0; j < width; ++j) {
  1509. X        *nextptr++ = *inptr++;
  1510. X        *nextptr++ = *inptr++;
  1511. X        *nextptr++ = *inptr++;
  1512. X    }
  1513. X    for (i = 0; i < length; ++i) {
  1514. X        tmpptr = thisline;
  1515. X        thisline = nextline;
  1516. X        nextline = tmpptr;
  1517. X        lastline = (i == imax);
  1518. X        if (fread(inline, 3*width, 1, in) <= 0)
  1519. X            break;
  1520. X        inptr = inline;
  1521. X        nextptr = nextline;
  1522. X        for (j = 0; j < width; ++j) {
  1523. X            *nextptr++ = *inptr++;
  1524. X            *nextptr++ = *inptr++;
  1525. X            *nextptr++ = *inptr++;
  1526. X        }
  1527. X        thisptr = thisline;
  1528. X        nextptr = nextline;
  1529. X        outptr = outline;
  1530. X        for (j = 0; j < width; ++j) {
  1531. X            int red, green, blue;
  1532. X            register int oval, r2, g2, b2;
  1533. X
  1534. X            lastpixel = (j == jmax);
  1535. X            b2 = *thisptr++;
  1536. X            g2 = *thisptr++;
  1537. X            r2 = *thisptr++;
  1538. X            if (r2 < 0)
  1539. X                r2 = 0;
  1540. X            else if (r2 >= MAX_COLOR)
  1541. X                r2 = MAX_COLOR-1;
  1542. X            if (g2 < 0)
  1543. X                g2 = 0;
  1544. X            else if (g2 >= MAX_COLOR)
  1545. X                g2 = MAX_COLOR-1;
  1546. X            if (b2 < 0)
  1547. X                b2 = 0;
  1548. X            else if (b2 >= MAX_COLOR)
  1549. X                b2 = MAX_COLOR-1;
  1550. X            red = r2;
  1551. X            green = g2;
  1552. X            blue = b2;
  1553. X            r2 >>= COLOR_SHIFT;
  1554. X            g2 >>= COLOR_SHIFT;
  1555. X            b2 >>= COLOR_SHIFT;
  1556. X            oval = histogram[r2][g2][b2];
  1557. X            if (oval == -1) {
  1558. X                int ci;
  1559. X                register int cj, tmp, d2, dist;
  1560. X                register C_cell    *cell;
  1561. X
  1562. X                cell = *(ColorCells +
  1563. X                    (((r2>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
  1564. X                    ((g2>>(B_DEPTH-C_DEPTH)) << C_DEPTH ) +
  1565. X                    (b2>>(B_DEPTH-C_DEPTH))));
  1566. X                if (cell == NULL )
  1567. X                    cell = create_colorcell(red,
  1568. X                        green, blue);
  1569. X                dist = 9999999;
  1570. X                for (ci = 0; ci < cell->num_ents && dist > cell->entries[ci][1]; ++ci) {
  1571. X                    cj = cell->entries[ci][0];
  1572. X                    d2 = (rm[cj] >> COLOR_SHIFT) - r2;
  1573. X                    d2 *= d2;
  1574. X                    tmp = (gm[cj] >> COLOR_SHIFT) - g2;
  1575. X                    d2 += tmp*tmp;
  1576. X                    tmp = (bm[cj] >> COLOR_SHIFT) - b2;
  1577. X                    d2 += tmp*tmp;
  1578. X                    if (d2 < dist) {
  1579. X                        dist = d2;
  1580. X                        oval = cj;
  1581. X                    }
  1582. X                }
  1583. X                histogram[r2][g2][b2] = oval;
  1584. X            }
  1585. X            *outptr++ = oval;
  1586. X            red -= rm[oval];
  1587. X            green -= gm[oval];
  1588. X            blue -= bm[oval];
  1589. X            if (!lastpixel) {
  1590. X                thisptr[0] += blue * 7 / 16;
  1591. X                thisptr[1] += green * 7 / 16;
  1592. X                thisptr[2] += red * 7 / 16;
  1593. X            }
  1594. X            if (!lastline) {
  1595. X                if (j != 0) {
  1596. X                    nextptr[-3] += blue * 3 / 16;
  1597. X                    nextptr[-2] += green * 3 / 16;
  1598. X                    nextptr[-1] += red * 3 / 16;
  1599. X                }
  1600. X                nextptr[0] += blue * 5 / 16;
  1601. X                nextptr[1] += green * 5 / 16;
  1602. X                nextptr[2] += red * 5 / 16;
  1603. X                if (!lastpixel) {
  1604. X                    nextptr[3] += blue / 16;
  1605. X                        nextptr[4] += green / 16;
  1606. X                        nextptr[5] += red / 16;
  1607. X                }
  1608. X                nextptr += 3;
  1609. X            }
  1610. X        }
  1611. X        if (fwrite(outline, width, 1, out) < 0)
  1612. X            break;
  1613. X    }
  1614. X    free(inline);
  1615. X    free(thisline);
  1616. X    free(nextline);
  1617. X    free(outline);
  1618. X}
  1619. SHAR_EOF
  1620. echo "extracting hamtosun"
  1621. sed 's/^X//' << \SHAR_EOF > hamtosun
  1622. X#! /bin/csh
  1623. X
  1624. Xiff2sun -cp $1 $1.out
  1625. Xconvert $1.out $1.pic
  1626. Xrasfilter8to1 -d $1.pic | screenload -g
  1627. X/bin/rm $1.out
  1628. SHAR_EOF
  1629. echo "End of archive 1 (of 1)"
  1630. # if you want to concatenate archives, remove anything after this line
  1631. exit
  1632.